#include <linux/fs.h>
#include <linux/module.h>
#include <linux/uaccess.h>

#define FILE_NAME "/tmp/testfile"

static struct file *file_ptr = NULL;

static int __init
fileop_init (void)
{
  // >>> 实现文件访问操作。
  //
  // if true
  //     printk(KERN_INFO "File operation successful\n")
  //   printk(KERN_ALERT "Failed to open file\n")
  
  // Solution 1(Failed)
  // mm_segment_t old_fs;
  // char buf[128];
  // loff_t pos = 0;
  // old_fs = get_fs();
  // set_fs(KERNEL_DS);
  // file_ptr = filp_open(FILE_NAME, O_RDWR | O_CREAT, 0644);
  // if (IS_ERR(file_ptr)) {
  //   printk(KERN_ALERT "Failed to open file\n");
  //   return PTR_ERR(file_ptr);
  // }
  // vfs_read(file_ptr, buf, sizeof(buf), &pos);
  // pos = 0;
  // vfs_write(file_ptr, "hello", 5, &pos);
  // set_fs(old_fs);
  // printk(KERN_INFO "File operation successful\n");

  // Solution 2(Failed)
  // struct path path;
  // char buf[128];
  // loff_t pos = 0;
  // // if (kern_path(FILE_NAME, LOOKUP_FOLLOW, &path) != 0) {
  // if (kernfs_path(FILE_NAME, LOOKUP_FOLLOW, &path) != 0) {
  //   printk(KERN_ALERT "Failed to open file\n");
  //   return -ENOENT;
  // }
  // file_ptr = dentry_open(&path, O_RDWR | O_CREAT, current_cred());
  // if (IS_ERR(file_ptr)) {
  //   printk(KERN_ALERT "Failed to open file\n");
  //   return PTR_ERR(file_ptr);
  // }
  // vfs_read(file_ptr, buf, sizeof(buf), &pos);
  // pos = 0;
  // vfs_write(file_ptr, "hello", 5, &pos);
  // printk(KERN_INFO "File operation successful\n");

  // Solution 3(Failed)
  // char buf[128];
  // loff_t pos = 0;
  // file_ptr = filp_open(FILE_NAME, O_RDWR | O_CREAT, 0644);
  // if (IS_ERR(file_ptr)) {
  //   printk(KERN_ALERT "Failed to open file\n");
  //   return PTR_ERR(file_ptr);
  // }
  // vfs_read(file_ptr, buf, sizeof(buf), &pos);
  // pos = 0;
  // vfs_write(file_ptr, "hello", 5, &pos);
  // printk(KERN_INFO "File operation successful\n");

  // Solution 4()
  char buf[128];
  loff_t pos = 0;
  file_ptr = filp_open(FILE_NAME, O_RDWR | O_CREAT, 0644);
  if (IS_ERR(file_ptr)) {
    printk(KERN_ALERT "Failed to open file\n");
    return PTR_ERR(file_ptr);
  }
  kernel_read(file_ptr, buf, sizeof(buf), &pos);
  pos = 0;
  kernel_write(file_ptr, "hello", 5, &pos);
  printk(KERN_INFO "File operation successful\n");

  return 0;
}

static void __exit
fileop_exit (void)
{
  if (file_ptr)
    {
      filp_close (file_ptr, NULL);
      printk (KERN_INFO "File closed\n");
    }
}

module_init (fileop_init);
module_exit (fileop_exit);

MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Your Name");
MODULE_DESCRIPTION ("Simple File Operation Module");
